package com.ming.sportdemo.Aop;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.ming.sportdemo.annotation.UserToken;
import com.ming.sportdemo.bean.User;
import com.ming.sportdemo.service.UserService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

@Aspect
@Repository
public class UserTokenAop {

    @Autowired
    UserService userService;

    @Pointcut("@annotation(com.ming.sportdemo.annotation.UserToken)")
    public void token(){
    }

    @Around("token()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        Object[] args = joinPoint.getArgs();
        HttpServletRequest request = (HttpServletRequest) args[0];
        //HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String token = request.getHeader("token");
        Object proceed = null;
        //获取类的字节码对象，通过字节码对象获取方法信息
        Class c1 = joinPoint.getTarget().getClass();
        //获取方法签名(通过此签名获取目标方法信息)
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = c1.getDeclaredMethod(methodSignature.getName(), methodSignature.getParameterTypes());
        UserToken userToken = method.getAnnotation(UserToken.class);
        if (userToken.required()) {
            // 执行认证
            if (token == null) {
                throw new RuntimeException("无token，请重新登录");
            }
            // 获取 token 中的 user id
            String userId = null;

            try {
                userId = JWT.decode(token).getAudience().get(0);
            } catch (JWTDecodeException j) {
                throw new RuntimeException("401");
            }
            User user = userService.getById(userId);
            if (user == null) {
                throw new RuntimeException("用户不存在，请重新登录");
            }
            // 验证 token
            JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getPassword())).build();
            try {
                jwtVerifier.verify(token);
            } catch (JWTVerificationException e) {
                throw new RuntimeException("401");
            }
            try {
                proceed = joinPoint.proceed();
                System.out.println(methodSignature.getName() + "操作token验证成功");
                return proceed;
            } catch (Throwable throwable) {
                System.out.println(methodSignature.getName() + "操作token验证失败");
                throwable.printStackTrace();
                return null;
            } finally {
                System.out.println("finish");
            }

        } else {
            System.out.println("token is not require");
            return joinPoint.proceed();
        }
    }
}
